#include "./src/shared.h"
#include "./src/types.h"

// Deferred shader textures
samplerRect dsEC;
samplerRect dsNorm;
samplerRect dsColor;

// Index into the light textures
//uniform vec3 lightPos[LIGHTS_PER_PASS];
//uniform vec3 lightDir[LIGHTS_PER_PASS];
//uniform vec4 lightColor[LIGHTS_PER_PASS];

//uniform vec2 lightIndex[LIGHTS_PER_PASS];
samplerRect lightDir;
samplerRect lightPos;
samplerRect lightColor;

samplerRect prevImage;
samplerRect prevNegImage;
samplerRect prevNegNormals;
uniform float lightOffset;
uniform float lightScale;
uniform float prevScale;
uniform float spotCosCutoff;
uniform float cAtt;
uniform float lAtt;
uniform float qAtt;

void main (void)
{
	vec4 finalColor;
	vec4 finalNegColor;
	vec4 finalNegNormal;
	vec2 indirectIndex;
#if 0
	vec3 n = normalize(textureRect(dsNorm, gl_FragCoord));
	vec3 position = textureRect(dsEC, gl_FragCoord);
	vec4 diffuse = textureRect(dsColor, gl_FragCoord);
#else
	vec3 n = normalize(textureRect(dsNorm, gl_FragCoord));
	vec3 position = textureRect(dsEC, gl_FragCoord);
	vec4 diffuse = textureRect(dsColor, gl_FragCoord);
#endif

	for (int i=0; i<LIGHTS_PER_PASS; ++i) {
		indirectIndex = vec2(mod(i+lightOffset, INDIRECT_LIGHTS_WIDTH), (i+lightOffset)/INDIRECT_LIGHTS_WIDTH);
		
		vec3 lightPosition = textureRect(lightPos, indirectIndex);
		vec3 lightDirection = textureRect(lightDir, indirectIndex);
		vec4 lightDiffuse = textureRect(lightColor, indirectIndex);

		// Required offset when lights are determined from the camera...
		lightPosition.z += 0.001;
		
		vec3 toLight = lightPosition - position;
		float dis = length(toLight);
		toLight = normalize(toLight);
		// TODO normalize required?
		float spotDot = dot(-toLight, normalize(lightDirection));
		float nDotL= max(0.0, dot(n,toLight));
		float nnDotL = min(0.0, dot(n, toLight));
    	float att, spotAtt=1.0, negSpotAtt=1.0;
#if 0
		if (spotDot < spotCosCutoff) {
			spotAtt = 0.0;
		} else {
			spotAtt = pow(spotDot, gl_LightSource[0].spotExponent);
		}
#endif
#if 0
		if (spotDot < spotCosCutoff) {
			//spotAtt = 0.0;
            negSpotAtt = 0.0;
		} else {
			//spotAtt = 1.0;
            //negSpotAtt = 1.0;
			//spotAtt = pow(spotDot, 1.0); //gl_LightSource[0].spotExponent);
			negSpotAtt = pow(spotDot, 2.0); //gl_LightSource[0].spotExponent);
		}
#endif
#if 1
		if (spotDot < spotCosCutoff) {
			//spotAtt = 0.0;
            negSpotAtt = 0.0;
		} else {
			//spotAtt = 1.0;
            negSpotAtt = 1.0;
			//spotAtt = pow(spotDot, 1.0); //gl_LightSource[0].spotExponent);
			negSpotAtt = pow(spotDot, 2.0); //gl_LightSource[0].spotExponent);
		}
#endif
		att = spotAtt * 1/(cAtt + lAtt*dis + qAtt*dis*dis);
        lightDiffuse *= att;
		finalColor += lightDiffuse * nDotL;
		finalNegColor += lightDiffuse * nnDotL * negSpotAtt;
        //finalNegNormal += vec4(toLight,0.0);
        finalNegNormal += vec4((toLight*negSpotAtt*-1), 0.0);
	}
	finalColor *= lightScale * diffuse;
    finalNegColor *= lightScale*-1;

	gl_FragData[0] = prevScale * textureRect(prevImage, gl_FragCoord) + finalColor;
#if NEGATIVE_LIGHT
	gl_FragData[1] = prevScale * textureRect(prevNegImage, gl_FragCoord) + finalNegColor;
	gl_FragData[2] = prevScale * textureRect(prevNegNormals, gl_FragCoord) + finalNegNormal;
#endif
}

